/* -*- Mode:C++; c-file-style:"gnu"; indent-tabs-mode:nil; -*- */
/*
 * Copyright (c) 2020 TELEMATICS LAB, Politecnico di Bari
 *
 * This file is part of 5G-air-simulator
 *
 * 5G-air-simulator is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 3 as
 * published by the Free Software Foundation;
 *
 * 5G-air-simulator is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with 5G-air-simulator; if not, see <http://www.gnu.org/licenses/>.
 *
 * Author: Telematics Lab <telematics-dev@poliba.it>
 * Author: Alessandro Grassi <alessandro.grassi@poliba.it>
 */



#include "AMCModule.h"
#include "../../load-parameters.h"
#include "../../utility/miesm-effective-sinr.h"
#include <math.h>
#include "iostream"

int CQIIndex[15] =
{
  1, 2, 3, 4, 5, 6,      //QPSK
  7, 8, 9,               //16-QAM
  10, 11, 12, 13, 14, 15 //64-QAM
};

int MapCQIToMCS[15] =
{
  0, 1, 3, 5, 7, 9,      //QPSK
  11, 13, 15,            //16-QAM
  18, 20, 22, 24, 26, 28 //64-QAM
};

double EfficiencyForCQIIndex[15] =
{
  0.15, 0.23, 0.38, 0.6, 0.88, 1.18,
  1.48, 1.91, 2.41,
  2.73, 3.32, 3.9, 4.52, 5.12, 5.55
};

int MCSIndex[32] =
{
  0,  1,  2,  3,  4,  5,  6,  7,  8,  9,           //QPSK
  10, 11, 12, 13, 14, 15, 16,                      //16-QAM
  17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,  //64-QAM
  29, 30, 31                                       //RESERVED
};

int ModulationSchemeForMCSIndex[32] =
{
  2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
  4, 4, 4, 4, 4, 4, 4,
  6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6,
  0, 0, 0                                   //Not defined
};

double EfficiencyForMCSIndex[32] =
{
  0,
  0.15, 0.19, 0.23, 0.31, 0.38, 0.49, 0.6, 0.74, 0.88, 1.03, 1.18,
  1.33, 1.48, 1.7, 1.91, 2.16, 2.41, 2.57,
  2.73, 3.03, 3.32, 3.61, 3.9, 4.21, 4.52, 4.82, 5.12, 5.33, 5.55,
  2.4,
  0
};

double SINRForCQIIndex_legacy[15] =
{
  -6.75,
  -4.96,
  -2.96,
  -1.01,
  0.96,
  2.88,
  4.92,
  6.70,
  8.72,
  10.51,
  12.45,
  14.35,
  16.07,
  17.88,
  19.97
};
/*
double SINRForCQIIndex_extended[15] =
{
  -6.75,
  -2.96,
  0.96,
  4.92,
  6.70,
  8.72,
  10.51,
  12.45,
  14.35,
  16.07,
  17.88,
  19.97,
  22.0,
  24.0,
  26.0
};
*/
double SINRForCQIIndex_extended[15] =
{
  -6.7500,
  -3.4107,
  -0.0714,
  3.2679,
  6.6071,
  9.9464,
  13.2857,
  16.6250,
  19.9643,
  23.3036,
  26.6429,
  29.9821,
  33.3214,
  36.6607,
  40.0000
};

/*
double SINRForCQIIndex[15] = {
 -4.63, -2.6, -0.12, 2.26, 4.73,
 7.53, 8.67, 11.32,
 14.24, 15.21, 18.63, 21.32, 23.47, 28.49, 34.6
 };
*/

int TransportBlockSize[32] =
{
  0,
  18, 23, 28, 37, 45, 59, 72, 89, 105, 123, 141,
  159, 177, 203, 230, 259, 289,
  308, 328, 363, 399, 433, 468, 506, 543, 578, 614, 640,
  667, 288,
  0
};

// Table 7.1.7.1-1 of 3GPP TS 36.213 v8.8.0
int McsToItbs[29] =
{
  0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 9, 10, 11, 12, 13, 14, 15, 15, 16, 17, 18,
  19, 20, 21, 22, 23, 24, 25, 26
};

// 3GPP TS 36.213 - Table 7.1.7.2.1-1: Transport block size table (dimension 27×110)
int TransportBlockSizeTable [110][27] =
{
               /* MCS0    MCS1    MCS2    MCS3   MCS4     MCS5    MCS6    MCS7    MCS8    MCS9    MCS10/11 MCS12  MCS13   MCS14   MCS15   MCS16/17 MCS18  MCS19   MCS20   MCS21   MCS22   MCS23   MCS24   MCS25   MCS26   MCS27   MCS28 */
  /* NPRB 001*/ { 16,     24,     32,     40,     56,     72,     88,     104,    120,    136,    144,    176,    208,    224,    256,    280,    328,    336,    376,    408,    440,    488,    520,    552,    584,    616,    712},   /* NPRB 001 */
  /* NPRB 002*/ { 32,     56,     72,     104,    120,    144,    176,    224,    256,    296,    328,    376,    440,    488,    552,    600,    632,    696,    776,    840,    904,    1000,   1064,   1128,   1192,   1256,   1480},  /* NPRB 002 */
  /* NPRB 003*/ { 56,     88,     144,    176,    208,    224,    256,    328,    392,    456,    504,    584,    680,    744,    840,    904,    968,    1064,   1160,   1288,   1384,   1480,   1608,   1736,   1800,   1864,   2216},  /* NPRB 003 */
  /* NPRB 004*/ { 88,     144,    176,    208,    256,    328,    392,    472,    536,    616,    680,    776,    904,    1000,   1128,   1224,   1288,   1416,   1544,   1736,   1864,   1992,   2152,   2280,   2408,   2536,   2984},  /* NPRB 004 */
  /* NPRB 005*/ { 120,    176,    208,    256,    328,    424,    504,    584,    680,    776,    872,    1000,   1128,   1256,   1416,   1544,   1608,   1800,   1992,   2152,   2344,   2472,   2664,   2856,   2984,   3112,   3752},  /* NPRB 005 */
  /* NPRB 006*/ { 152,    208,    256,    328,    408,    504,    600,    712,    808,    936,    1032,   1192,   1352,   1544,   1736,   1800,   1928,   2152,   2344,   2600,   2792,   2984,   3240,   3496,   3624,   3752,   4392},  /* NPRB 006 */
  /* NPRB 007*/ { 176,    224,    296,    392,    488,    600,    712,    840,    968,    1096,   1224,   1384,   1608,   1800,   1992,   2152,   2280,   2536,   2792,   2984,   3240,   3496,   3752,   4008,   4264,   4392,   5160},  /* NPRB 007 */
  /* NPRB 008*/ { 208,    256,    328,    440,    552,    680,    808,    968,    1096,   1256,   1384,   1608,   1800,   2024,   2280,   2472,   2600,   2856,   3112,   3496,   3752,   4008,   4264,   4584,   4968,   5160,   5992},  /* NPRB 008 */
  /* NPRB 009*/ { 224,    328,    376,    504,    632,    776,    936,    1096,   1256,   1416,   1544,   1800,   2024,   2280,   2600,   2728,   2984,   3240,   3624,   3880,   4136,   4584,   4776,   5160,   5544,   5736,   6712},  /* NPRB 009 */
  /* NPRB 010*/ { 256,    344,    424,    568,    696,    872,    1032,   1224,   1384,   1544,   1736,   2024,   2280,   2536,   2856,   3112,   3240,   3624,   4008,   4264,   4584,   4968,   5352,   5736,   5992,   6200,   7480},  /* NPRB 010 */
  /* NPRB 011*/ { 288,    376,    472,    616,    776,    968,    1128,   1320,   1544,   1736,   1928,   2216,   2472,   2856,   3112,   3368,   3624,   4008,   4392,   4776,   5160,   5544,   5992,   6200,   6712,   6968,   8248},  /* NPRB 011 */
  /* NPRB 012*/ { 328,    424,    520,    680,    840,    1032,   1224,   1480,   1672,   1864,   2088,   2408,   2728,   3112,   3496,   3624,   3880,   4392,   4776,   5160,   5544,   5992,   6456,   6968,   7224,   7480,   8760},  /* NPRB 012 */
  /* NPRB 013*/ { 344,    456,    568,    744,    904,    1128,   1352,   1608,   1800,   2024,   2280,   2600,   2984,   3368,   3752,   4008,   4264,   4776,   5160,   5544,   5992,   6456,   6968,   7480,   7992,   8248,   9528},  /* NPRB 013 */
  /* NPRB 014*/ { 376,    488,    616,    808,    1000,   1224,   1480,   1672,   1928,   2216,   2472,   2792,   3240,   3624,   4008,   4264,   4584,   5160,   5544,   5992,   6456,   6968,   7480,   7992,   8504,   8760,   10296}, /* NPRB 014 */
  /* NPRB 015*/ { 392,    520,    648,    872,    1064,   1320,   1544,   1800,   2088,   2344,   2664,   2984,   3368,   3880,   4264,   4584,   4968,   5352,   5992,   6456,   6968,   7480,   7992,   8504,   9144,   9528,   11064}, /* NPRB 015 */
  /* NPRB 016*/ { 424,    568,    696,    904,    1128,   1384,   1672,   1928,   2216,   2536,   2792,   3240,   3624,   4136,   4584,   4968,   5160,   5736,   6200,   6968,   7480,   7992,   8504,   9144,   9912,   10296,  11832}, /* NPRB 016 */
  /* NPRB 017*/ { 456,    600,    744,    968,    1192,   1480,   1736,   2088,   2344,   2664,   2984,   3496,   3880,   4392,   4968,   5160,   5544,   6200,   6712,   7224,   7992,   8504,   9144,   9912,   10296,  10680,  12576}, /* NPRB 017 */
  /* NPRB 018*/ { 488,    632,    776,    1032,   1288,   1544,   1864,   2216,   2536,   2856,   3112,   3624,   4136,   4584,   5160,   5544,   5992,   6456,   7224,   7736,   8248,   9144,   9528,   10296,  11064,  11448,  13536}, /* NPRB 018 */
  /* NPRB 019*/ { 504,    680,    840,    1096,   1352,   1672,   1992,   2344,   2664,   2984,   3368,   3880,   4392,   4968,   5544,   5736,   6200,   6712,   7480,   8248,   8760,   9528,   10296,  11064,  11448,  12216,  14112}, /* NPRB 019 */
  /* NPRB 020*/ { 536,    712,    872,    1160,   1416,   1736,   2088,   2472,   2792,   3112,   3496,   4008,   4584,   5160,   5736,   6200,   6456,   7224,   7992,   8504,   9144,   9912,   10680,  11448,  12216,  12576,  14688}, /* NPRB 020 */
  /* NPRB 021*/ { 568,    744,    936,    1224,   1480,   1864,   2216,   2536,   2984,   3368,   3752,   4264,   4776,   5352,   5992,   6456,   6712,   7480,   8248,   9144,   9912,   10680,  11448,  12216,  12960,  13536,  15264}, /* NPRB 021 */
  /* NPRB 022*/ { 600,    776,    968,    1256,   1544,   1928,   2280,   2664,   3112,   3496,   3880,   4392,   4968,   5736,   6200,   6712,   7224,   7992,   8760,   9528,   10296,  11064,  11832,  12576,  13536,  14112,  16416}, /* NPRB 022 */
  /* NPRB 023*/ { 616,    808,    1000,   1320,   1608,   2024,   2408,   2792,   3240,   3624,   4008,   4584,   5352,   5992,   6456,   6968,   7480,   8248,   9144,   9912,   10680,  11448,  12576,  12960,  14112,  14688,  16992}, /* NPRB 023 */
  /* NPRB 024*/ { 648,    872,    1064,   1384,   1736,   2088,   2472,   2984,   3368,   3752,   4264,   4776,   5544,   6200,   6968,   7224,   7736,   8760,   9528,   10296,  11064,  12216,  12960,  13536,  14688,  15264,  17568}, /* NPRB 024 */
  /* NPRB 025*/ { 680,    904,    1096,   1416,   1800,   2216,   2600,   3112,   3496,   4008,   4392,   4968,   5736,   6456,   7224,   7736,   7992,   9144,   9912,   10680,  11448,  12576,  13536,  14112,  15264,  15840,  18336}, /* NPRB 025 */
  /* NPRB 026*/ { 712,    936,    1160,   1480,   1864,   2280,   2728,   3240,   3624,   4136,   4584,   5352,   5992,   6712,   7480,   7992,   8504,   9528,   10296,  11064,  12216,  12960,  14112,  14688,  15840,  16416,  19080}, /* NPRB 026 */
  /* NPRB 027*/ { 744,    968,    1192,   1544,   1928,   2344,   2792,   3368,   3752,   4264,   4776,   5544,   6200,   6968,   7736,   8248,   8760,   9912,   10680,  11448,  12576,  13536,  14688,  15264,  16416,  16992,  19848}, /* NPRB 027 */
  /* NPRB 028*/ { 776,    1000,   1256,   1608,   1992,   2472,   2984,   3368,   3880,   4392,   4968,   5736,   6456,   7224,   7992,   8504,   9144,   10296,  11064,  12216,  12960,  14112,  15264,  15840,  16992,  17568,  20616}, /* NPRB 028 */
  /* NPRB 029*/ { 776,    1032,   1288,   1672,   2088,   2536,   2984,   3496,   4008,   4584,   5160,   5992,   6712,   7480,   8248,   8760,   9528,   10296,  11448,  12576,  13536,  14688,  15840,  16416,  17568,  18336,  21384}, /* NPRB 029 */
  /* NPRB 030*/ { 808,    1064,   1320,   1736,   2152,   2664,   3112,   3624,   4264,   4776,   5352,   5992,   6712,   7736,   8504,   9144,   9912,   10680,  11832,  12960,  14112,  15264,  16416,  16992,  18336,  19080,  22152}, /* NPRB 030 */
  /* NPRB 031*/ { 840,    1128,   1384,   1800,   2216,   2728,   3240,   3752,   4392,   4968,   5544,   6200,   6968,   7992,   8760,   9528,   9912,   11064,  12216,  13536,  14688,  15840,  16992,  17568,  19080,  19848,  22920}, /* NPRB 031 */
  /* NPRB 032*/ { 872,    1160,   1416,   1864,   2280,   2792,   3368,   3880,   4584,   5160,   5736,   6456,   7224,   8248,   9144,   9912,   10296,  11448,  12576,  13536,  14688,  15840,  16992,  18336,  19848,  20616,  23688}, /* NPRB 032 */
  /* NPRB 033*/ { 904,    1192,   1480,   1928,   2344,   2856,   3496,   4008,   4584,   5160,   5736,   6712,   7480,   8504,   9528,   10296,  10680,  11832,  12960,  14112,  15264,  16416,  17568,  19080,  19848,  20616,  24496}, /* NPRB 033 */
  /* NPRB 034*/ { 936,    1224,   1544,   1992,   2408,   2984,   3496,   4136,   4776,   5352,   5992,   6968,   7736,   8760,   9912,   10296,  11064,  12216,  13536,  14688,  15840,  16992,  18336,  19848,  20616,  21384,  25456}, /* NPRB 034 */
  /* NPRB 035*/ { 968,    1256,   1544,   2024,   2472,   3112,   3624,   4264,   4968,   5544,   6200,   6968,   7992,   9144,   9912,   10680,  11448,  12576,  14112,  15264,  16416,  17568,  19080,  19848,  21384,  22152,  25456}, /* NPRB 035 */
  /* NPRB 036*/ { 1000,   1288,   1608,   2088,   2600,   3112,   3752,   4392,   4968,   5736,   6200,   7224,   8248,   9144,   10296,  11064,  11832,  12960,  14112,  15264,  16992,  18336,  19080,  20616,  22152,  22920,  26416}, /* NPRB 036 */
  /* NPRB 037*/ { 1032,   1352,   1672,   2152,   2664,   3240,   3880,   4584,   5160,   5736,   6456,   7480,   8504,   9528,   10680,  11448,  12216,  13536,  14688,  15840,  16992,  18336,  19848,  21384,  22920,  23688,  27376}, /* NPRB 037 */
  /* NPRB 038*/ { 1032,   1384,   1672,   2216,   2728,   3368,   4008,   4584,   5352,   5992,   6712,   7736,   8760,   9912,   11064,  11832,  12216,  13536,  15264,  16416,  17568,  19080,  20616,  22152,  22920,  24496,  28336}, /* NPRB 038 */
  /* NPRB 039*/ { 1064,   1416,   1736,   2280,   2792,   3496,   4136,   4776,   5544,   6200,   6712,   7736,   8760,   9912,   11064,  11832,  12576,  14112,  15264,  16992,  18336,  19848,  21384,  22152,  23688,  24496,  29296}, /* NPRB 039 */
  /* NPRB 040*/ { 1096,   1416,   1800,   2344,   2856,   3496,   4136,   4968,   5544,   6200,   6968,   7992,   9144,   10296,  11448,  12216,  12960,  14688,  15840,  16992,  18336,  19848,  21384,  22920,  24496,  25456,  29296}, /* NPRB 040 */
  /* NPRB 041*/ { 1128,   1480,   1800,   2408,   2984,   3624,   4264,   4968,   5736,   6456,   7224,   8248,   9528,   10680,  11832,  12576,  13536,  14688,  16416,  17568,  19080,  20616,  22152,  23688,  25456,  26416,  30576}, /* NPRB 041 */
  /* NPRB 042*/ { 1160,   1544,   1864,   2472,   2984,   3752,   4392,   5160,   5992,   6712,   7480,   8504,   9528,   10680,  12216,  12960,  13536,  15264,  16416,  18336,  19848,  21384,  22920,  24496,  25456,  26416,  30576}, /* NPRB 042 */
  /* NPRB 043*/ { 1192,   1544,   1928,   2536,   3112,   3752,   4584,   5352,   5992,   6712,   7480,   8760,   9912,   11064,  12216,  12960,  14112,  15264,  16992,  18336,  19848,  21384,  22920,  24496,  26416,  27376,  31704}, /* NPRB 043 */
  /* NPRB 044*/ { 1224,   1608,   1992,   2536,   3112,   3880,   4584,   5352,   6200,   6968,   7736,   8760,   9912,   11448,  12576,  13536,  14112,  15840,  17568,  19080,  20616,  22152,  23688,  25456,  26416,  28336,  32856}, /* NPRB 044 */
  /* NPRB 045*/ { 1256,   1608,   2024,   2600,   3240,   4008,   4776,   5544,   6200,   6968,   7992,   9144,   10296,  11448,  12960,  13536,  14688,  16416,  17568,  19080,  20616,  22920,  24496,  25456,  27376,  28336,  32856}, /* NPRB 045 */
  /* NPRB 046*/ { 1256,   1672,   2088,   2664,   3240,   4008,   4776,   5736,   6456,   7224,   7992,   9144,   10680,  11832,  12960,  14112,  14688,  16416,  18336,  19848,  21384,  22920,  24496,  26416,  28336,  29296,  34008}, /* NPRB 046 */
  /* NPRB 047*/ { 1288,   1736,   2088,   2728,   3368,   4136,   4968,   5736,   6456,   7480,   8248,   9528,   10680,  12216,  13536,  14688,  15264,  16992,  18336,  20616,  22152,  23688,  25456,  27376,  28336,  29296,  35160}, /* NPRB 047 */
  /* NPRB 048*/ { 1320,   1736,   2152,   2792,   3496,   4264,   4968,   5992,   6712,   7480,   8504,   9528,   11064,  12216,  13536,  14688,  15840,  17568,  19080,  20616,  22152,  24496,  25456,  27376,  29296,  30576,  35160}, /* NPRB 048 */
  /* NPRB 049*/ { 1352,   1800,   2216,   2856,   3496,   4392,   5160,   5992,   6968,   7736,   8504,   9912,   11064,  12576,  14112,  15264,  15840,  17568,  19080,  21384,  22920,  24496,  26416,  28336,  29296,  31704,  36696}, /* NPRB 049 */
  /* NPRB 050*/ { 1384,   1800,   2216,   2856,   3624,   4392,   5160,   6200,   6968,   7992,   8760,   9912,   11448,  12960,  14112,  15264,  16416,  18336,  19848,  21384,  22920,  25456,  27376,  28336,  30576,  31704,  36696}, /* NPRB 050 */
  /* NPRB 051*/ { 1416,   1864,   2280,   2984,   3624,   4584,   5352,   6200,   7224,   7992,   9144,   10296,  11832,  12960,  14688,  15840,  16416,  18336,  19848,  22152,  23688,  25456,  27376,  29296,  31704,  32856,  37888}, /* NPRB 051 */
  /* NPRB 052*/ { 1416,   1864,   2344,   2984,   3752,   4584,   5352,   6456,   7224,   8248,   9144,   10680,  11832,  13536,  14688,  15840,  16992,  19080,  20616,  22152,  24496,  26416,  28336,  29296,  31704,  32856,  37888}, /* NPRB 052 */
  /* NPRB 053*/ { 1480,   1928,   2344,   3112,   3752,   4776,   5544,   6456,   7480,   8248,   9144,   10680,  12216,  13536,  15264,  16416,  16992,  19080,  21384,  22920,  24496,  26416,  28336,  30576,  32856,  34008,  39232}, /* NPRB 053 */
  /* NPRB 054*/ { 1480,   1992,   2408,   3112,   3880,   4776,   5736,   6712,   7480,   8504,   9528,   11064,  12216,  14112,  15264,  16416,  17568,  19848,  21384,  22920,  25456,  27376,  29296,  30576,  32856,  34008,  40576}, /* NPRB 054 */
  /* NPRB 055*/ { 1544,   1992,   2472,   3240,   4008,   4776,   5736,   6712,   7736,   8760,   9528,   11064,  12576,  14112,  15840,  16992,  17568,  19848,  22152,  23688,  25456,  27376,  29296,  31704,  34008,  35160,  40576}, /* NPRB 055 */
  /* NPRB 056*/ { 1544,   2024,   2536,   3240,   4008,   4968,   5992,   6712,   7736,   8760,   9912,   11448,  12576,  14688,  15840,  16992,  18336,  20616,  22152,  24496,  26416,  28336,  30576,  31704,  34008,  35160,  40576}, /* NPRB 056 */
  /* NPRB 057*/ { 1608,   2088,   2536,   3368,   4136,   4968,   5992,   6968,   7992,   9144,   9912,   11448,  12960,  14688,  16416,  17568,  18336,  20616,  22920,  24496,  26416,  28336,  30576,  32856,  35160,  36696,  42368}, /* NPRB 057 */
  /* NPRB 058*/ { 1608,   2088,   2600,   3368,   4136,   5160,   5992,   6968,   7992,   9144,   10296,  11832,  12960,  14688,  16416,  17568,  19080,  20616,  22920,  25456,  27376,  29296,  31704,  32856,  35160,  36696,  42368}, /* NPRB 058 */
  /* NPRB 059*/ { 1608,   2152,   2664,   3496,   4264,   5160,   6200,   7224,   8248,   9144,   10296,  11832,  13536,  15264,  16992,  18336,  19080,  21384,  23688,  25456,  27376,  29296,  31704,  34008,  36696,  37888,  43816}, /* NPRB 059 */
  /* NPRB 060*/ { 1672,   2152,   2664,   3496,   4264,   5352,   6200,   7224,   8504,   9528,   10680,  12216,  13536,  15264,  16992,  18336,  19848,  21384,  23688,  25456,  28336,  30576,  32856,  34008,  36696,  37888,  43816}, /* NPRB 060 */
  /* NPRB 061*/ { 1672,   2216,   2728,   3624,   4392,   5352,   6456,   7480,   8504,   9528,   10680,  12216,  14112,  15840,  17568,  18336,  19848,  22152,  24496,  26416,  28336,  30576,  32856,  35160,  36696,  39232,  45352}, /* NPRB 061 */
  /* NPRB 062*/ { 1736,   2280,   2792,   3624,   4392,   5544,   6456,   7480,   8760,   9912,   11064,  12576,  14112,  15840,  17568,  19080,  19848,  22152,  24496,  26416,  29296,  31704,  34008,  35160,  37888,  39232,  45352}, /* NPRB 062 */
  /* NPRB 063*/ { 1736,   2280,   2856,   3624,   4584,   5544,   6456,   7736,   8760,   9912,   11064,  12576,  14112,  16416,  18336,  19080,  20616,  22920,  24496,  27376,  29296,  31704,  34008,  36696,  37888,  40576,  46888}, /* NPRB 063 */
  /* NPRB 064*/ { 1800,   2344,   2856,   3752,   4584,   5736,   6712,   7736,   9144,   10296,  11448,  12960,  14688,  16416,  18336,  19848,  20616,  22920,  25456,  27376,  29296,  31704,  34008,  36696,  39232,  40576,  46888}, /* NPRB 064 */
  /* NPRB 065*/ { 1800,   2344,   2856,   3752,   4584,   5736,   6712,   7992,   9144,   10296,  11448,  12960,  14688,  16992,  18336,  19848,  21384,  23688,  25456,  28336,  30576,  32856,  35160,  37888,  39232,  40576,  48936}, /* NPRB 065 */
  /* NPRB 066*/ { 1800,   2408,   2984,   3880,   4776,   5736,   6968,   7992,   9144,   10296,  11448,  13536,  15264,  16992,  19080,  20616,  21384,  23688,  26416,  28336,  30576,  32856,  35160,  37888,  40576,  42368,  48936}, /* NPRB 066 */
  /* NPRB 067*/ { 1864,   2472,   2984,   3880,   4776,   5992,   6968,   8248,   9528,   10680,  11832,  13536,  15264,  16992,  19080,  20616,  22152,  24496,  26416,  29296,  31704,  34008,  36696,  37888,  40576,  42368,  48936}, /* NPRB 067 */
  /* NPRB 068*/ { 1864,   2472,   3112,   4008,   4968,   5992,   6968,   8248,   9528,   10680,  11832,  13536,  15264,  17568,  19848,  20616,  22152,  24496,  27376,  29296,  31704,  34008,  36696,  39232,  42368,  43816,  51024}, /* NPRB 068 */
  /* NPRB 069*/ { 1928,   2536,   3112,   4008,   4968,   5992,   7224,   8504,   9528,   11064,  12216,  14112,  15840,  17568,  19848,  21384,  22152,  24496,  27376,  29296,  31704,  35160,  36696,  39232,  42368,  43816,  51024}, /* NPRB 069 */
  /* NPRB 070*/ { 1928,   2536,   3112,   4136,   4968,   6200,   7224,   8504,   9912,   11064,  12216,  14112,  15840,  18336,  19848,  21384,  22920,  25456,  27376,  30576,  32856,  35160,  37888,  40576,  42368,  43816,  52752}, /* NPRB 070 */
  /* NPRB 071*/ { 1992,   2600,   3240,   4136,   5160,   6200,   7480,   8760,   9912,   11064,  12576,  14112,  16416,  18336,  20616,  22152,  22920,  25456,  28336,  30576,  32856,  35160,  37888,  40576,  43816,  45352,  52752}, /* NPRB 071 */
  /* NPRB 072*/ { 1992,   2600,   3240,   4264,   5160,   6200,   7480,   8760,   9912,   11448,  12576,  14688,  16416,  18336,  20616,  22152,  23688,  26416,  28336,  30576,  34008,  36696,  39232,  40576,  43816,  45352,  52752}, /* NPRB 072 */
  /* NPRB 073*/ { 2024,   2664,   3240,   4264,   5160,   6456,   7736,   8760,   10296,  11448,  12960,  14688,  16416,  19080,  20616,  22152,  23688,  26416,  29296,  31704,  34008,  36696,  39232,  42368,  45352,  46888,  55056}, /* NPRB 073 */
  /* NPRB 074*/ { 2088,   2728,   3368,   4392,   5352,   6456,   7736,   9144,   10296,  11832,  12960,  14688,  16992,  19080,  21384,  22920,  24496,  26416,  29296,  31704,  34008,  36696,  40576,  42368,  45352,  46888,  55056}, /* NPRB 074 */
  /* NPRB 075*/ { 2088,   2728,   3368,   4392,   5352,   6712,   7736,   9144,   10680,  11832,  12960,  15264,  16992,  19080,  21384,  22920,  24496,  27376,  29296,  32856,  35160,  37888,  40576,  43816,  45352,  46888,  55056}, /* NPRB 075 */
  /* NPRB 076*/ { 2088,   2792,   3368,   4392,   5544,   6712,   7992,   9144,   10680,  11832,  13536,  15264,  17568,  19848,  22152,  23688,  24496,  27376,  30576,  32856,  35160,  37888,  40576,  43816,  46888,  48936,  55056}, /* NPRB 076 */
  /* NPRB 077*/ { 2152,   2792,   3496,   4584,   5544,   6712,   7992,   9528,   10680,  12216,  13536,  15840,  17568,  19848,  22152,  23688,  25456,  27376,  30576,  32856,  35160,  39232,  42368,  43816,  46888,  48936,  57336}, /* NPRB 077 */
  /* NPRB 078*/ { 2152,   2856,   3496,   4584,   5544,   6968,   8248,   9528,   11064,  12216,  13536,  15840,  17568,  19848,  22152,  23688,  25456,  28336,  30576,  34008,  36696,  39232,  42368,  45352,  46888,  48936,  57336}, /* NPRB 078 */
  /* NPRB 079*/ { 2216,   2856,   3496,   4584,   5736,   6968,   8248,   9528,   11064,  12576,  14112,  15840,  18336,  20616,  22920,  24496,  25456,  28336,  31704,  34008,  36696,  39232,  42368,  45352,  48936,  51024,  57336}, /* NPRB 079 */
  /* NPRB 080*/ { 2216,   2856,   3624,   4776,   5736,   6968,   8248,   9912,   11064,  12576,  14112,  16416,  18336,  20616,  22920,  24496,  26416,  29296,  31704,  34008,  36696,  40576,  43816,  45352,  48936,  51024,  59256}, /* NPRB 080 */
  /* NPRB 081*/ { 2280,   2984,   3624,   4776,   5736,   7224,   8504,   9912,   11448,  12960,  14112,  16416,  18336,  20616,  22920,  24496,  26416,  29296,  31704,  35160,  37888,  40576,  43816,  46888,  48936,  51024,  59256}, /* NPRB 081 */
  /* NPRB 082*/ { 2280,   2984,   3624,   4776,   5992,   7224,   8504,   9912,   11448,  12960,  14688,  16416,  19080,  21384,  23688,  25456,  26416,  29296,  32856,  35160,  37888,  40576,  43816,  46888,  51024,  52752,  59256}, /* NPRB 082 */
  /* NPRB 083*/ { 2280,   2984,   3752,   4776,   5992,   7224,   8760,   10296,  11448,  12960,  14688,  16992,  19080,  21384,  23688,  25456,  27376,  30576,  32856,  35160,  39232,  42368,  45352,  46888,  51024,  52752,  61664}, /* NPRB 083 */
  /* NPRB 084*/ { 2344,   3112,   3752,   4968,   5992,   7480,   8760,   10296,  11832,  13536,  14688,  16992,  19080,  21384,  24496,  25456,  27376,  30576,  32856,  36696,  39232,  42368,  45352,  48936,  51024,  52752,  61664}, /* NPRB 084 */
  /* NPRB 085*/ { 2344,   3112,   3880,   4968,   5992,   7480,   8760,   10296,  11832,  13536,  14688,  16992,  19080,  22152,  24496,  26416,  27376,  30576,  34008,  36696,  39232,  42368,  45352,  48936,  52752,  55056,  61664}, /* NPRB 085 */
  /* NPRB 086*/ { 2408,   3112,   3880,   4968,   6200,   7480,   9144,   10680,  12216,  13536,  15264,  17568,  19848,  22152,  24496,  26416,  28336,  30576,  34008,  36696,  40576,  43816,  46888,  48936,  52752,  55056,  63776}, /* NPRB 086 */
  /* NPRB 087*/ { 2408,   3240,   3880,   5160,   6200,   7736,   9144,   10680,  12216,  13536,  15264,  17568,  19848,  22152,  25456,  26416,  28336,  31704,  34008,  37888,  40576,  43816,  46888,  51024,  52752,  55056,  63776}, /* NPRB 087 */
  /* NPRB 088*/ { 2472,   3240,   4008,   5160,   6200,   7736,   9144,   10680,  12216,  14112,  15264,  17568,  19848,  22920,  25456,  27376,  28336,  31704,  35160,  37888,  40576,  43816,  46888,  51024,  52752,  55056,  63776}, /* NPRB 088 */
  /* NPRB 089*/ { 2472,   3240,   4008,   5160,   6456,   7736,   9144,   11064,  12576,  14112,  15840,  18336,  20616,  22920,  25456,  27376,  29296,  31704,  35160,  37888,  42368,  45352,  48936,  51024,  55056,  57336,  66592}, /* NPRB 089 */
  /* NPRB 090*/ { 2536,   3240,   4008,   5352,   6456,   7992,   9528,   11064,  12576,  14112,  15840,  18336,  20616,  22920,  25456,  27376,  29296,  32856,  35160,  39232,  42368,  45352,  48936,  51024,  55056,  57336,  66592}, /* NPRB 090 */
  /* NPRB 091*/ { 2536,   3368,   4136,   5352,   6456,   7992,   9528,   11064,  12576,  14112,  15840,  18336,  20616,  23688,  26416,  28336,  29296,  32856,  36696,  39232,  42368,  45352,  48936,  52752,  55056,  57336,  66592}, /* NPRB 091 */
  /* NPRB 092*/ { 2536,   3368,   4136,   5352,   6456,   7992,   9528,   11448,  12960,  14688,  16416,  18336,  21384,  23688,  26416,  28336,  30576,  32856,  36696,  39232,  42368,  46888,  48936,  52752,  57336,  59256,  68808}, /* NPRB 092 */
  /* NPRB 093*/ { 2600,   3368,   4136,   5352,   6712,   8248,   9528,   11448,  12960,  14688,  16416,  19080,  21384,  23688,  26416,  28336,  30576,  34008,  36696,  40576,  43816,  46888,  51024,  52752,  57336,  59256,  68808}, /* NPRB 093 */
  /* NPRB 094*/ { 2600,   3496,   4264,   5544,   6712,   8248,   9912,   11448,  12960,  14688,  16416,  19080,  21384,  24496,  27376,  29296,  30576,  34008,  37888,  40576,  43816,  46888,  51024,  55056,  57336,  59256,  68808}, /* NPRB 094 */
  /* NPRB 095*/ { 2664,   3496,   4264,   5544,   6712,   8248,   9912,   11448,  13536,  15264,  16992,  19080,  21384,  24496,  27376,  29296,  30576,  34008,  37888,  40576,  43816,  46888,  51024,  55056,  57336,  61664,  71112}, /* NPRB 095 */
  /* NPRB 096*/ { 2664,   3496,   4264,   5544,   6968,   8504,   9912,   11832,  13536,  15264,  16992,  19080,  22152,  24496,  27376,  29296,  31704,  35160,  37888,  40576,  45352,  48936,  51024,  55056,  59256,  61664,  71112}, /* NPRB 096 */
  /* NPRB 097*/ { 2728,   3496,   4392,   5736,   6968,   8504,   10296,  11832,  13536,  15264,  16992,  19848,  22152,  25456,  28336,  29296,  31704,  35160,  37888,  42368,  45352,  48936,  52752,  55056,  59256,  61664,  71112}, /* NPRB 097 */
  /* NPRB 098*/ { 2728,   3624,   4392,   5736,   6968,   8760,   10296,  11832,  13536,  15264,  16992,  19848,  22152,  25456,  28336,  30576,  31704,  35160,  39232,  42368,  45352,  48936,  52752,  57336,  59256,  61664,  73712}, /* NPRB 098 */
  /* NPRB 099*/ { 2728,   3624,   4392,   5736,   6968,   8760,   10296,  12216,  14112,  15840,  17568,  19848,  22920,  25456,  28336,  30576,  31704,  35160,  39232,  42368,  46888,  48936,  52752,  57336,  61664,  63776,  73712}, /* NPRB 099 */
  /* NPRB 100*/ { 2792,   3624,   4584,   5736,   7224,   8760,   10296,  12216,  14112,  15840,  17568,  19848,  22920,  25456,  28336,  30576,  32856,  36696,  39232,  43816,  46888,  51024,  55056,  57336,  61664,  63776,  75376}, /* NPRB 100 */
  /* NPRB 101*/ { 2792,   3752,   4584,   5992,   7224,   8760,   10680,  12216,  14112,  15840,  17568,  20616,  22920,  26416,  29296,  30576,  32856,  36696,  40576,  43816,  46888,  51024,  55056,  57336,  61664,  63776,  75376}, /* NPRB 101 */
  /* NPRB 102*/ { 2856,   3752,   4584,   5992,   7224,   9144,   10680,  12576,  14112,  16416,  18336,  20616,  23688,  26416,  29296,  31704,  32856,  36696,  40576,  43816,  46888,  51024,  55056,  59256,  61664,  63776,  75376}, /* NPRB 102 */
  /* NPRB 103*/ { 2856,   3752,   4584,   5992,   7480,   9144,   10680,  12576,  14688,  16416,  18336,  20616,  23688,  26416,  29296,  31704,  34008,  36696,  40576,  43816,  48936,  51024,  55056,  59256,  63776,  66592,  75376}, /* NPRB 103 */
  /* NPRB 104*/ { 2856,   3752,   4584,   5992,   7480,   9144,   10680,  12576,  14688,  16416,  18336,  21384,  23688,  26416,  29296,  31704,  34008,  37888,  40576,  45352,  48936,  52752,  57336,  59256,  63776,  66592,  75376}, /* NPRB 104 */
  /* NPRB 105*/ { 2984,   3880,   4776,   6200,   7480,   9144,   11064,  12960,  14688,  16416,  18336,  21384,  23688,  27376,  30576,  31704,  34008,  37888,  42368,  45352,  48936,  52752,  57336,  59256,  63776,  66592,  75376}, /* NPRB 105 */
  /* NPRB 106*/ { 2984,   3880,   4776,   6200,   7480,   9528,   11064,  12960,  14688,  16992,  18336,  21384,  24496,  27376,  30576,  32856,  34008,  37888,  42368,  45352,  48936,  52752,  57336,  61664,  63776,  66592,  75376}, /* NPRB 106 */
  /* NPRB 107*/ { 2984,   3880,   4776,   6200,   7736,   9528,   11064,  12960,  15264,  16992,  19080,  21384,  24496,  27376,  30576,  32856,  35160,  39232,  42368,  46888,  48936,  52752,  57336,  61664,  66592,  68808,  75376}, /* NPRB 107 */
  /* NPRB 108*/ { 2984,   4008,   4776,   6200,   7736,   9528,   11448,  12960,  15264,  16992,  19080,  22152,  24496,  27376,  30576,  32856,  35160,  39232,  42368,  46888,  51024,  55056,  59256,  61664,  66592,  68808,  75376}, /* NPRB 108 */
  /* NPRB 109*/ { 2984,   4008,   4968,   6456,   7736,   9528,   11448,  13536,  15264,  16992,  19080,  22152,  24496,  28336,  31704,  34008,  35160,  39232,  43816,  46888,  51024,  55056,  59256,  61664,  66592,  68808,  75376}, /* NPRB 109 */
  /* NPRB 110*/ { 3112,   4008,   4968,   6456,   7992,   9528,   11448,  13536,  15264,  17568,  19080,  22152,  25456,  28336,  31704,  34008,  35160,  39232,  43816,  46888,  51024,  55056,  59256,  63776,  66592,  71112,  75376}  /* NPRB 110 */
               /* MCS0    MCS1    MCS2    MCS3    MCS4    MCS5    MCS6    MCS7    MCS8    MCS9    MCS10/11 MCS12  MCS13   MCS14   MCS15   MCS16/17 MCS18  MCS19   MCS20   MCS21   MCS22   MCS23   MCS24   MCS25   MCS26   MCS27   MCS28 */
};

int const TbsL1ToL2Translation[2][120] =
{
  { 1544, 1608, 1672, 1736, 1800, 1864, 1928, 1992, 2024, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536, 2600, 2664, 2728, 2792, 2856, 2984, 3112, 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160,  5352,  5544,  5736,  5992,  6200,  6456,  6712,  6968,  7224,  7480,  7736,  7992,  8248,  8504,  8760,  9144,  9528,  9912,  10296, 10680, 11064, 11448, 11832, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416, 27376, 28336, 29296, 30576, 31704, 32856, 34008, 35160, 36696, 37888, 39232, 40576, 42368, 43816, 45352, 46888, 48936, 51024,  52752,  55056,  57336,  59256,  61664,  63776,  66592,  68808,  71112,  73712,  75376,  76208,  78704,  81176,  84760,  87936,  90816,  93800,  97896  },
  { 3112, 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4008, 4136, 4264, 4392, 4584, 4776, 4776, 4968, 5160, 5160, 5352, 5544, 5544, 5736, 5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 8248, 8504, 8760, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 11832, 12576, 12960, 13536, 14112, 14688, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 25456, 27376, 28336, 29296, 30576, 31704, 32856, 34008, 35160, 36696, 37888, 39232, 40576, 42368, 43816, 45352, 46888, 48936, 51024, 52752, 55056, 57336, 59256, 61664, 63776, 66592, 68808, 71112, 73712, 76208, 78704, 81176, 84760, 87936, 90816, 93800, 97896, 101840, 105528, 110136, 115040, 119816, 124464, 128496, 133208, 137792, 142248, 146856, 149776, 152976, 157432, 161760, 169544, 175600, 181656, 187712, 195816 }
};

int const TbsL1ToL3Translation[2][134] =
{
  { 1032, 1064, 1096, 1128, 1160, 1192, 1224, 1256, 1288, 1320, 1352, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 1992, 2024, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536, 2600, 2664, 2728, 2792, 2856, 2984, 3112, 3240, 3368,  3496, 3624,  3752,  3880,  4008,  4136,  4264,  4392,  4584,  4776,  4968,  5160,  5352,  5544,  5736,  5992,  6200,  6456,  6712,  6968,  7224,  7480,  7736,  7992,  8248,  8504,  8760,  9144,  9528,  9912,  10296, 10680, 11064, 11448, 11832, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416, 27376, 28336, 29296, 30576, 31704, 32856, 34008,  35160,  36696,  37888,  39232,  40576,  42368,  43816,  45352,  46888,  48936,  51024,  52752,  55056,  57336,  59256,  61664,  63776,  66592,  68808,  71112,  73712,  75376,  76208,  78704,  81176,  84760,  87936,  90816,  93800,  97896  },
  { 3112, 3240, 3240, 3368, 3496, 3624, 3624, 3752, 3880, 4008, 4008, 4136, 4264, 4392, 4584, 4776, 4968, 5160, 5352, 5544, 5736, 5992, 5992, 6200, 6456, 6712, 6712, 6968, 7224, 7480, 7480, 7736, 7992, 8248, 8248, 8504, 8760, 9144, 9528, 9912, 10296, 10680, 11064, 11448, 11832, 12576, 12960, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 18336, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416, 27376, 28336, 29296, 30576, 31704, 32856, 34008, 35160, 36696, 37888, 39232, 40576, 42368, 43816, 45352, 46888, 48936, 51024, 52752, 55056, 57336, 59256, 61664, 63776, 66592, 68808, 71112, 73712, 76208, 78704, 81176, 84760, 87936, 90816, 93800, 97896, 101840, 105528, 110136, 115040, 119816, 119816, 128496, 133208, 137792, 142248, 146856, 152976, 157432, 165216, 171888, 177816, 185728, 191720, 199824, 205880, 214176, 221680, 226416, 230104, 236160, 245648, 254328, 266440, 275376, 284608, 293736 }
};

int const TbsL1ToL4Translation[2][142] =
{
  { 776,  808,  840,  872,  904,  936,  968,  1000, 1032, 1064, 1096, 1128, 1160, 1192, 1224, 1256, 1288, 1320, 1352, 1384, 1416, 1480, 1544, 1608, 1672, 1736, 1800, 1864, 1928, 1992, 2024, 2088, 2152, 2216, 2280, 2344, 2408, 2472, 2536,  2600,  2664,  2728,  2792,  2856,  2984,  3112,  3240,  3368,  3496,  3624,  3752,  3880,  4008,  4136,  4264,  4392,  4584,  4776,  4968,  5160,  5352,  5544,  5736,  5992,  6200,  6456,  6712,  6968,  7224,  7480,  7736,  7992,  8248,  8504,  8760,  9144,  9528,  9912,  10296, 10680, 11064, 11448, 11832, 12216, 12576, 12960, 13536, 14112, 14688, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456,  26416,  27376,  28336,  29296,  30576,  31704,  32856,  34008,  35160,  36696,  37888,  39232,  40576,  42368,  43816,  45352,  46888,  48936,  51024,  52752,  55056,  57336,  59256,  61664,  63776,  66592,  68808,  71112,  73712,  75376,  76208,  78704,  81176,  84760,  87936,  90816,  93800,  97896  },
  { 3112, 3240, 3368, 3496, 3624, 3752, 3880, 4008, 4136, 4264, 4392, 4584, 4584, 4776, 4968, 4968, 5160, 5352, 5352, 5544, 5736, 5992, 6200, 6456, 6712, 6968, 7224, 7480, 7736, 7992, 7992, 8248, 8504, 8760, 9144, 9528, 9528, 9912, 10296, 10296, 10680, 11064, 11064, 11448, 11832, 12576, 12960, 13536, 14112, 14688, 15264, 15264, 15840, 16416, 16992, 17568, 18336, 19080, 19848, 20616, 21384, 22152, 22920, 23688, 24496, 25456, 26416, 28336, 29296, 29296, 30576, 31704, 32856, 34008, 35160, 36696, 37888, 39232, 40576, 42368, 43816, 45352, 46888, 48936, 51024, 51024, 55056, 57336, 59256, 61664, 63776, 66592, 68808, 71112, 73712, 76208, 78704, 81176, 84760, 87936, 90816, 93800, 97896, 101840, 105528, 110136, 115040, 115040, 124464, 128496, 133208, 137792, 142248, 146856, 151376, 157432, 161760, 169544, 175600, 181656, 187712, 195816, 203704, 211936, 220296, 230104, 236160, 245648, 254328, 266440, 275376, 284608, 293736, 299856, 305976, 314888, 324336, 339112, 351224, 363336, 375448, 391656 }
};

AMCModule::AMCModule()
{
  setUseExtendedCQI (false);
}

AMCModule::~AMCModule()
{}

int
AMCModule::GetCQIFromEfficiency (double Efficiency)
{
  int cqi = 1; // == CQIIndex[0]
  while (EfficiencyForCQIIndex[cqi] < Efficiency && cqi <= 14)
    {
      cqi++;
    }
  return cqi;
}

bool
AMCModule::getUseExtendedCQI (void)
{
  return m_useExtendedCQI;
}

void
AMCModule::setUseExtendedCQI (bool t)
{
  m_useExtendedCQI = t;
  if (t == false)
    {
      SINRForCQIIndex = SINRForCQIIndex_legacy;
    }
  else
    {
      SINRForCQIIndex = SINRForCQIIndex_extended;
    }
}

int
AMCModule::GetCQIFromSinr (double sinr)
{
  int cqi = 1; // == CQIIndex[0]
  while (SINRForCQIIndex[cqi] <= sinr && cqi <= 14)
    {
      cqi++;
    }
  return cqi;
}

double
AMCModule::GetSinrFromCQI (int cqi)
{
  double sinr = SINRForCQIIndex[cqi-1]+0.1;
  return sinr;
}

int
AMCModule::GetMCSFromCQI (int cqi)
{
  return MapCQIToMCS [cqi-1];
}

int
AMCModule::GetCQIFromMCS (int mcs)
{
  int cqi = 0;
  for (int i=0; i<15; i++)
    {
      if (mcs <= MapCQIToMCS[i])
        {
          cqi = i+1;
          break;
        }
    }
  return cqi;
}

int
AMCModule::GetMCSIndexFromEfficiency(double efficiency)
{
  int mcs = 1;
  while (EfficiencyForMCSIndex[mcs] < efficiency && mcs < 30)
    {
      mcs++;
    }
  return mcs;
}

int
AMCModule::GetTBSizeFromMCS (int mcs)
{
  return TransportBlockSizeTable[0][McsToItbs[mcs]];
}

int
AMCModule::GetTBSizeFromMCS (int mcs, int nbRBs)
{
  int itbs = McsToItbs[mcs];
  return (TransportBlockSizeTable[nbRBs - 1][itbs]);
}

int
AMCModule::GetTBSizeFromMCS (int mcs, int nbRBs, int nbLayers)
{
  int itbs = McsToItbs[mcs];
  int tbs;
  int baselineTbs;
  switch(nbLayers)
    {
    case 1:
      tbs = TransportBlockSizeTable[nbRBs - 1][itbs];
      break;

    case 2:
      if( nbRBs < 56)
        {
          tbs = TransportBlockSizeTable[nbRBs * 2 - 1][itbs];
        }
      else
        {
          baselineTbs = TransportBlockSizeTable[nbRBs - 1][itbs];
          // TODO: optimize using dicotomic search, because data is already ordered
          for (int i = 0; i < 120; i++)
            {
              if( TbsL1ToL2Translation[0][i] == baselineTbs)
                {
                  tbs = TbsL1ToL2Translation[1][i];
                  break;
                }
            }
        }
      break;

    case 3:
      if( nbRBs < 37)
        {
          tbs = TransportBlockSizeTable[nbRBs * 3 - 1][itbs];
        }
      else
        {
          baselineTbs = TransportBlockSizeTable[nbRBs - 1][itbs];
          // TODO: optimize using dicotomic search, because data is already ordered
          for (int i = 0; i < 134; i++)
            {
              if( TbsL1ToL3Translation[0][i] == baselineTbs)
                {
                  tbs = TbsL1ToL3Translation[1][i];
                  break;
                }
            }
        }
      break;

    case 4:
      if( nbRBs < 28)
        {
          tbs = TransportBlockSizeTable[nbRBs * 4 - 1][itbs];
        }
      else
        {
          baselineTbs = TransportBlockSizeTable[nbRBs - 1][itbs];
          // TODO: optimize using dicotomic search, because data is already ordered
          for (int i = 0; i < 142; i++)
            {
              if( TbsL1ToL4Translation[0][i] == baselineTbs)
                {
                  tbs = TbsL1ToL4Translation[1][i];
                  break;
                }
            }
        }
      break;

    default:
      cout << "Invalid number of layers for TBS calculation: " << nbLayers << endl;
      exit(1);
      break;
    }
  return tbs;
}


int
AMCModule::GetTBSizeFromMCS (int mcs1, int mcs2, int nbRBs, int rank)
{
  int tbs;
  switch(rank)
    {
    case 1:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 1);
      break;
    case 2:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 1) + GetTBSizeFromMCS (mcs2, nbRBs, 1);
      break;
    case 3:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 1) + GetTBSizeFromMCS (mcs2, nbRBs, 2);
      break;
    case 4:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 2) + GetTBSizeFromMCS (mcs2, nbRBs, 2);
      break;
    case 5:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 2) + GetTBSizeFromMCS (mcs2, nbRBs, 3);
      break;
    case 6:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 3) + GetTBSizeFromMCS (mcs2, nbRBs, 3);
      break;
    case 7:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 3) + GetTBSizeFromMCS (mcs2, nbRBs, 4);
      break;
    case 8:
      tbs = GetTBSizeFromMCS (mcs1, nbRBs, 4) + GetTBSizeFromMCS (mcs2, nbRBs, 4);
      break;
    default:
      cout << "Invalid rank for TBS calculation: " << rank << endl;
      exit(1);
      break;
    }
  return tbs;
}

double
AMCModule::GetEfficiencyFromCQI (int cqi)
{
  int mcs = GetMCSFromCQI (cqi);
  int bits = GetTBSizeFromMCS (mcs,1);
  //eff = rate / bandwidth
  double eff = (bits/0.001)/180000.;
  return eff;
}


int AMCModule::GetModulationOrderFromMCS(int mcs)
{
  return ModulationSchemeForMCSIndex[mcs];
}


int AMCModule::GetMCSFromSinrVector(const vector<double> &sinr)
{
  int mcs = 0;
  for (int modulationOrder=2; modulationOrder<7; modulationOrder+=2)
    {
      double estimated_effsinr = GetMiesmEffectiveSinr(sinr, modulationOrder);
      int estimated_cqi = GetCQIFromSinr(estimated_effsinr);
      int estimated_mcs = GetMCSFromCQI(estimated_cqi);
      int estimated_modulation_order = GetModulationOrderFromMCS(estimated_mcs);
      if(estimated_modulation_order == modulationOrder)
        {
          mcs = estimated_mcs;
        }
    }
  return mcs;
}

vector<int>
AMCModule::CreateCqiFeedbacks (vector<double> sinr)
{
DEBUG_LOG_START_1(SIM_ENV_TEST_CQI_FEEDBACKS)
  cout << "Creating CQI feedbacks" << endl;
DEBUG_LOG_END

  vector<int> cqi;
  for (auto sinr_ : sinr)
    {
      int cqi_ = GetCQIFromSinr (sinr_);

DEBUG_LOG_START_1(SIM_ENV_TEST_CQI_FEEDBACKS)
      cout << "\t sinr " << sinr_ << " cqi " << cqi_ << endl;
DEBUG_LOG_END

      cqi.push_back (cqi_);
    }

  return cqi;
}
